#version 330 core

in vec4 vcolor;
//in vec2 normalizedXY;
out vec4 FragColor;

uniform mat4 projMatrix;    //  投影矩阵
uniform int renderStep;     //  渲染步骤
uniform vec3 volumeXYZ;    //  体数据长宽高 mediump
uniform vec2 viewportWH;            //渲染的视口大小 mediump
uniform float opacity;      //不透明度 mediump
uniform float brightness;   //亮度 mediump
uniform float alphaThreshold;   // 不透明度阈值
uniform float alphaGradient;   // 不透明度梯度比例

// 纹理采样器  opengl一次着色至少可提供16个纹理单元同时工作
uniform sampler1D colorMapTex;  //  灰度转彩色映射采样器 mediump
uniform sampler2D bottomTex;    //  底面的纹理采样器 mediump
uniform sampler2D bgColorTex;   //  背景颜色缓冲采样器
uniform sampler2D bgDepthTex;   //  背景深度缓冲采样器
uniform sampler3D volumeDataTex;    //  三维体数据纹理采样器 mediump

void main(void)
{
    if(renderStep == 1){        //  画底部
        FragColor = vcolor;
    }else if(renderStep == 2){        //  画顶部减去底部
        vec4 samplecolor;       //mediump
        float rsum=0.0f,gsum=0.0f,bsum=0.0f,asum=1.0f, calc_opacity=0.0f;    //  初始颜色 mediump
        vec3 pos = vcolor.xyz;        // 当前的采样位置 mediump
        vec3 raydir;
        float front_z, step_z, step_w, bg_depth;
        //        mediump vec3 raydir = texture(bottomTex, normalizedXY).xyz; // 光线投射向量
        // vec3 raydir = texture(bottomTex, gl_FragCoord.xy/viewportWH).xyz; // 光线投射向量 mediump
        samplecolor = texture(bottomTex, gl_FragCoord.xy/viewportWH); // 光线投射向量 mediump\

        raydir = samplecolor.xyz;           // 底部的采样坐标
        raydir = raydir - pos;              //计算出光线穿过的向量
        int count = int(length(raydir * volumeXYZ));       // //计算出光线步进次数
        raydir = raydir / float(count);     //计算出光线步进向量
        count = int(count <= 10000) * count + int(count > 10000) * 10000;

//        FragColor = vec4(pos,1.0);
//       // FragColor = vec4(float(count)/100.0f);
//        return;


//        step_z = (samplecolor.w - projMatrix[3][2])/projMatrix[2][2];   //  终止位置的投影矩阵之前的z值
//        front_z = (vcolor.w - projMatrix[3][2])/projMatrix[2][2];  //  起始位置的投影矩阵之前的z值

//        float z = (vcolor.w - projMatrix[3][2])/projMatrix[2][2];    //projMatrix[列][行] 由投影后的zn计算投影前的ze值
//        float w = projMatrix[2][3] * z + projMatrix[3][3];
//        z = z * projMatrix[2][2] +  projMatrix[3][2];//vcolor.w;
//        z = z/w;
//        z = (z + 1.0f)/2.0f;
//        FragColor = vec4(z);
////        FragColor = vec4(abs(gl_FragCoord.z - z) * 100000.0f); // vec4(z); //与计算结果非常接近
//        return;

        front_z = vcolor.w;
        step_z = samplecolor.w - front_z;
        step_z = step_z / float(int(count<1)*1 + int(count>0)*count);    //  步进投影矩阵之前的z
//        FragColor = vec4(-1.0f * step_z/2.0f);
//        return;

        bg_depth = texture(bgDepthTex, gl_FragCoord.xy/viewportWH).x;
//        FragColor = vec4(bg_depth);
//        return;

        for(;count>0;count--){
            step_w = (front_z - projMatrix[3][2])/projMatrix[2][2];
            step_w = projMatrix[2][3]  * step_w + projMatrix[3][3];     //计算归一化的深度值
            step_w = front_z / step_w;
            step_w = (step_w + 1.0f)/2.0f;
//            FragColor = vec4(step_w);
//            return;
            if(step_w > bg_depth){
                //  光线经过的位置已经大于背景的深度缓冲了
//                FragColor = vec4(step_w);
//                return;
                break;
            }
            samplecolor = texture(volumeDataTex, pos);

            calc_opacity = alphaGradient * abs(samplecolor.r - calc_opacity);
            calc_opacity = opacity * (1.0f + calc_opacity);
            calc_opacity = calc_opacity * float(samplecolor.r>alphaThreshold);
            rsum = rsum + samplecolor.r * calc_opacity * asum;
            asum = asum - calc_opacity;
//            asum = asum * (1.0f - float(samplecolor.r>alphaThreshold)*opacity);
            if(asum < 0.0001f) break;
            pos = pos + raydir;
            front_z = front_z + step_z;
            calc_opacity = samplecolor.r;
        }
//        FragColor = vec4(step_w);
//        return;

        rsum = brightness * rsum;
//        FragColor = vec4(rsum, rsum, rsum, 1.0f - asum );
//        FragColor = vec4(texture(colorMapTex, rsum).xyz, 1.0f - asum );

        samplecolor = texture(colorMapTex, rsum);   //颜色映射
        rsum = samplecolor.r;
        gsum = samplecolor.g;
        bsum = samplecolor.b;
        asum = 1.0f - asum;
        samplecolor = texture(bgColorTex, gl_FragCoord.xy/viewportWH); //背景颜色
        rsum = asum * rsum + (1.0f - asum) * samplecolor.r;
        gsum = asum * gsum + (1.0f - asum) * samplecolor.g;
        bsum = asum * bsum + (1.0f - asum) * samplecolor.b;
        asum = asum + samplecolor.a;
        FragColor = vec4(rsum,gsum,bsum,asum);
//        gl_FragDepth = float(bg_depth < gl_FragCoord.z) * bg_depth
//                + float(bg_depth >= gl_FragCoord.z) * gl_FragCoord.z;
    }else{
        FragColor = vcolor;
    }
}
